﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;

namespace IGolovkine.AoA.BinarySerialization
{
    public class BinaryReader : IBinaryReader
    {
        private readonly System.IO.BinaryReader _reader;
        public BinaryReader(Stream stream)
        {
            _reader = new System.IO.BinaryReader(stream);
        }

        public int ReadInt32()
        {
            return _reader.ReadInt32();
        }

        public string ReadString()
        {
            return _reader.ReadString();
        }

        public T ReadObject<T>() where T : IBinarySerializable
        {
            return (T)this.ReadObjectLoose(typeof(T));
        }

        private IBinarySerializable ReadObjectLoose(Type type)
        {
            if (type == null)
            {
                throw new ArgumentException("type");
            }

            ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(IBinaryReader) }, null);
            if (constructor == null)
            {
                string message = string.Format("'{0}' doesn't implement a Non-Public contructor accepting IBinaryReader as the only parameter", type.Name);
                throw new ArgumentException(message);
            }

            return (IBinarySerializable)constructor.Invoke(new object[] { this });
        }

        public IBinarySerializable[] ReadObjectArray()
        {
            TypeMap map = this.ReadObject<TypeMap>();
            IBinarySerializable[] result = new IBinarySerializable[map.Count];
            for (int i = 0; i < result.Length; i++)
            {
                result[i] = this.ReadObjectLoose(map.GetMappedTypeAt(i));
            }
            return result;
        }

        public byte[] ReadByteArray()
        {
            int length = _reader.ReadInt32();
            return _reader.ReadBytes(length);
        }
    }
}
